package com.yzh.luckydraw.domain.strategy.service.algorithm.impl;

import com.yzh.luckydraw.domain.strategy.model.vo.AwardRateInfo;
import com.yzh.luckydraw.domain.strategy.service.algorithm.BaseAlgorithm;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * 总体概率：必中奖策略，排除已经中奖的概率，重新计算抽奖范围
 */
@Component("entiretyRateRandomDrawAlgorithm")
public class EntiretyRateRandomDrawAlgorithm extends BaseAlgorithm {
    @Override
    public String randomDraw(Long strategyId, List<String> excludeAwardIds) {
        BigDecimal newRateSum = BigDecimal.ZERO;
        List<AwardRateInfo> newAwardRateList = new ArrayList<>();
        List<AwardRateInfo> oldAwardRateList = awardRateInfoMap.get(strategyId);
        for (AwardRateInfo awardRateInfo : oldAwardRateList) {
            //将抽空的奖品剔除掉
            if (excludeAwardIds.contains(awardRateInfo.getAwardId())) {
                continue;
            }
            newAwardRateList.add(new AwardRateInfo(awardRateInfo.getAwardId(), awardRateInfo.getAwardRate()));
            //统计新的概率和
            newRateSum = newRateSum.add(awardRateInfo.getAwardRate());
        }
        //奖品列表为0，返回null
        if (newAwardRateList.size() == 0) {
            return null;
        }
        if (newAwardRateList.size() == 1) {
            return newAwardRateList.get(0).getAwardId();
        }
        //获取百位随机抽奖值
        int randomVal = generateSecureRandomIntCode(100);
        int cursorVal = 0;
        for (AwardRateInfo awardRateInfo : newAwardRateList) {
            /**
             * 有抽空的奖品需要重新计算概率，公式：当前商品概率 / 总概率
             * BigDecimal.ROUND_UP：无论正负，最后一位小数进位（0除外）
             * 例如：0.05 / 0.6 ≈ 0.08 -> 0.09 * 100 = 9 
             */
            int rateVal = awardRateInfo.getAwardRate().divide(newRateSum, 2, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)).intValue();
            if (randomVal <= (cursorVal + rateVal)) {
                return awardRateInfo.getAwardId();
            }
            cursorVal += rateVal;
        }
        return null;
    }
}
